package com.jrgiii.mbcr;


import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

import android.os.Binder;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import org.json.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Hashtable;
import java.util.List;



public class MBCRActivity extends MapActivity implements Runnable {
	public static final String PREFS_NAME = "MBCRPreferencesFile";
	private MapView mapView;
	private MapController mc;
	private Resources res;
	public Context myContext;
	private Toast threeDots;
	private Toast twoDots;
	private Toast oneDot;
	private Toast noDots;
	private String lineSelection;
	private boolean dieNow;
	private Thread updater;
	private SharedPreferences settings;
	
	private static final int ABOUT_DIALOG = 1;
    private static final int LINE_DIALOG  = 2;
	
	/** Called when the activity is first created. */
	@Override
	public void onBackPressed()
	{
		super.onBackPressed();
		dieNow = true;

		finish();
	}
	
	@Override

	public void onCreate(Bundle savedInstanceState) {
		myContext = this.getApplicationContext();
		super.onCreate(savedInstanceState);
		dieNow = false;
		threeDots = Toast.makeText(this, " . . . ", Toast.LENGTH_SHORT);
		twoDots = Toast.makeText(this, " . . ", Toast.LENGTH_SHORT);
		oneDot = Toast.makeText(this, " . ", Toast.LENGTH_SHORT);
		noDots = Toast.makeText(this, "!", Toast.LENGTH_SHORT);
		setContentView(R.layout.main);
		res = getResources();

		settings = getSharedPreferences(PREFS_NAME, 0);
		lineSelection = settings.getString("Lines", "YYYYYYYYYYYY");
		int zoomLevel = settings.getInt("ZoomLevel", 11);
		int latitude = settings.getInt("latitude", (int) (42.049293 * 1E6));
		int longitude = settings.getInt("longitude", (int) (-71.240845 * 1E6));
		GeoPoint hereIAm = new GeoPoint(latitude, longitude);
		mapView = (MapView) findViewById(R.id.mapview1);
		mapView.setBuiltInZoomControls(true);
		mapView.displayZoomControls(false);
		mc = mapView.getController();
		mc.setZoom(zoomLevel);
		mc.animateTo(hereIAm);
		mapView.invalidate();
		updater  = new Thread(this);
		updater.setDaemon(true);
		updater.start();
	}

	@Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog = null;
        switch (id)
        {
        case ABOUT_DIALOG: 
        	dialog = buildAbout();
        	break;
        case LINE_DIALOG:
        	break;
        default:
        	super.onCreateDialog(id);
        		
        }

        return dialog;
	}
	private Dialog buildAbout() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		ListView myView = new ListView(this);
		builder.setMessage(R.string.attrib1);
		return builder.create();
		// TODO Auto-generated method stub
		
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public 	boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.mbcrmenu, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection    
		switch (item.getItemId()) 
		{
		case R.id.exitButton:
			dieNow = true;
			finish();
			return true;
		case R.id.saveView:
			GeoPoint whereIAm = mapView.getMapCenter();
			int zoomLevel = mapView.getZoomLevel();
			setView(whereIAm, zoomLevel); 
			return true;
		
		case R.id.defaultView:
			setView(new GeoPoint((int) (42.049293 * 1E6), (int) (-71.240845 * 1E6)), 11); 
			return true;
		case R.id.about:
			showDialog(ABOUT_DIALOG);
			return true;
		default:            
					return super.onOptionsItemSelected(item);    
		}
	}
	
	private void setView(GeoPoint whereIAm, int zoomLevel) {
		Editor _edit = settings.edit(); 
		_edit.putInt("ZoomLevel", zoomLevel);
		_edit.putInt("latitude", whereIAm.getLatitudeE6());
		_edit.putInt("longitude", whereIAm.getLongitudeE6());
		_edit.commit();
	}

	@Override
	public void run() {
		//
		// begin an infinite loop
		//

		TrainLocations myLocs = new TrainLocations(res, res.getDrawable(R.drawable.train_image), this);
		Hashtable<String,TrainInfo> currentTrains = new Hashtable<String,TrainInfo>();
		long sleepTime = 200;
		int sleepsLeft = 1;
		while (true)
		{
			
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				continue;
			}
			//msgPoll.show();
			if (dieNow) return;
			sleepTime = 5000;
			if (--sleepsLeft > 0) {
/*				
				if (sleepsLeft == 3) threeDots.show();
				if (sleepsLeft == 2) twoDots.show();
				if (sleepsLeft == 1) oneDot.show();
*/
				continue;
			}
			sleepsLeft = 4;
			noDots.show();
			myLocs = new TrainLocations(res, res.getDrawable(R.drawable.train_image), this);
			currentTrains = new Hashtable<String,TrainInfo>();

			try {
				//msgFetch.show();
				for (int _line = 0; _line < lineSelection.length(); _line++)
				{
					char isOn = lineSelection.charAt(_line);
					if (isOn != 'Y') continue;
					String lineUrl = "http://developer.mbta.com/lib/RTCR/RailLine_" + (_line+1) + ".json";
					String thisData = readUrlAsString(lineUrl);
					JSONTokener tokens = new JSONTokener(thisData);
					JSONObject _obj = new JSONObject(tokens);
					JSONArray messageArray = _obj.getJSONArray("Messages");
					if (messageArray.length() == 0) {
						continue;
					}
					//msgProcess.show();
					for (int i = 0 ; i < messageArray.length(); i++)
					{
						JSONArray thisTrip = (JSONArray) messageArray.get(i);
						TrainInfo trip = buildTrainInfo(thisTrip);
						if (currentTrains.containsKey(trip.trainNumber)) continue;
						//if (trip.status.equalsIgnoreCase("sch")) continue;
						currentTrains.put(trip.trainNumber, trip);
						myLocs.addTrain(trip);
						//msgAdded.show();
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				continue;
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace(); 
				continue;
			}
			Overlay oldOne = null;
			List<Overlay> currentOnes = mapView.getOverlays();
			if (!currentOnes.isEmpty()) oldOne = currentOnes.get(0);
			if (myLocs.size() > 0) currentOnes.add(myLocs);
			if (oldOne != null) currentOnes.remove(oldOne);
			mapView.postInvalidate();
		}
		
		//
		// Must have been interrupted.. just exit
		//
	}

	private TrainInfo buildTrainInfo(JSONArray thisTrip) throws JSONException {
		// TODO Auto-generated method stub
		TrainInfo result = new TrainInfo();
		for (int j = 0; j < thisTrip.length(); j++) {
			JSONObject thisPair = (JSONObject) thisTrip.get(j);
			String _key = thisPair.getString("Key");
			String _val = thisPair.getString("Value");
			if (_key.equalsIgnoreCase("Trip")) result.trainNumber = _val;
			if (_key.equalsIgnoreCase("Destination")) result.destination = _val;
			if (_key.equalsIgnoreCase("Stop")) result.stopName = _val;
			if (_key.equalsIgnoreCase("Flag")) result.status = _val;
			if (_key.equalsIgnoreCase("Vehicle")) result.locomotiveNumber = _val;
			if (_key.equalsIgnoreCase("Latitude") && _val.length() > 0) result.latitude = Double.parseDouble(_val);
			if (_key.equalsIgnoreCase("Longitude") && _val.length() > 0) result.longititude = Double.parseDouble(_val);
			if (_key.equalsIgnoreCase("Heading") && _val.length() > 0) result.direction = Double.parseDouble(_val);
			if (_key.equalsIgnoreCase("Speed") && _val.length() > 0) result.speed = Double.parseDouble(_val);
			}		
		
		return result;
	}



	private String readUrlAsString(String urlPath) throws IOException { 
        StringBuffer fileData = new StringBuffer(10240);
        URL myUrl = new URL(urlPath);
        //msgurlOpen.show();
        
        InputStream _stream =  myUrl.openStream();
    	//msgopened.show();
       
        byte[] buf = new byte[128]; 
        int numRead=0; 
        while((numRead=_stream.read(buf)) != -1){ 
        	//msgreadblock.show();
        	byte[] smallBuf = new byte[numRead];
        	for (int i = 0; i < numRead; i++) smallBuf[i] = buf[i];
            String readData = new String(smallBuf); 
            fileData.append(readData); 
        } 
        _stream.close(); 
        return fileData.toString(); 
    }
	
}




